package org.light.jpa.verb;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.light.core.Writeable;
import org.light.domain.Domain;
import org.light.domain.Dropdown;
import org.light.domain.Field;
import org.light.domain.Method;
import org.light.domain.Signature;
import org.light.domain.Statement;
import org.light.domain.Type;
import org.light.exception.ValidateException;
import org.light.utils.DomainTokenUtil;
import org.light.utils.InterVarUtil;
import org.light.utils.StringUtil;
import org.light.utils.TableStringUtil;
import org.light.utils.WriteableUtil;

public class CountSearchByFieldsRecords extends org.light.limitedverb.CountSearchByFieldsRecords {
	@Override
	public Method generateDaoImplMethod() throws Exception {
		return null;
	}

	@Override
	public Method generateDaoMethodDefinition() throws Exception {
		return null;
	}

	@Override
	public Method generateServiceImplMethod() throws Exception {
		if (this.denied)
			return null;
		else {
			Method method = new Method();
			method.setStandardName("countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords");
			method.setReturnType(new Type("Integer"));
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDomainSuffix() + "."
					+ this.domain.getCapFirstDomainNameWithSuffix());
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getDaoSuffix() + "."
					+ this.domain.getStandardName() + "Dao");
			method.addAdditionalImport(this.domain.getPackageToken() + "." + this.domain.getServiceSuffix() + "."
					+ this.domain.getStandardName() + "Service");
			method.addSignature(new Signature(1, this.domain.getLowerFirstDomainName(), this.domain.getType()));
			method.setThrowException(true);
			method.addMetaData("Override");
			if (this.domain.containsDateTime()) {
				method.addAdditionalImport(this.domain.getPackageToken() + ".utils.DateUtil");
			}
			
			List<Writeable> sList = new ArrayList<Writeable>();
			sList.add(new Statement(3000L,2,"String jpql = \"select count(*) as countNum from "+this.domain.getCapFirstDomainNameWithSuffix()+" "+this.domain.getLowerFirstChar()+" where 1=1 \";"));
			long serial = 4000L;
			Set<Field> fields = this.domain.getSearchFields();
			for (Field f : fields) {
				if (!this.deniedFields.contains(f)) {
					if (f.getFieldType().equalsIgnoreCase("string")) {
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and "+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+" like CONCAT('%', '\"+"+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()+\"','%')\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					} else if ("date".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and date("+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+") = date('\"+DateUtil.utilDateToString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"())+\"')\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					}  else if ("datetime".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and date("+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+") = date('\"+DateUtil.utilDateTimeToString("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"())+\"')\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					} else if ("float".equalsIgnoreCase(f.getFieldType())||"double".equalsIgnoreCase(f.getFieldType())){
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and abs("+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+" - \"+"+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"()+\") < 0.0001\";"));
						sList.add(new Statement(serial + 200, 2,"}"));
					} else {
						sList.add(new Statement(serial, 2,
								"if ("+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"() != null) {"));
						sList.add(new Statement(serial + 100, 3,
								"jpql += \" and "+this.domain.getLowerFirstChar()+"."+f.getLowerFirstFieldName()+" = \"+"+this.domain.getLowerFirstDomainName()+".get"+f.getCapFirstFieldName()+"();"));
						sList.add(new Statement(serial + 200, 2,"}"));
					}
					serial += 1000L;
				}
			}
			sList.add(new Statement(serial,2,"Query query = entityManager.createQuery(jpql);"));
			sList.add(new Statement(serial+1000L,2,"Long count = (Long) query.getSingleResult();"));
			sList.add(new Statement(serial+2000L,2,"return count.intValue();"));
			method.setMethodStatementList(WriteableUtil.merge(sList));
			return method;
		}
	}

	public CountSearchByFieldsRecords(Domain domain) throws ValidateException {
		super();
		this.domain = domain;
		this.dbType = "MariaDB";
		this.denied = domain.isVerbDenied("SearchByFieldsByPage");
		this.verbName = "countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords";
	}
	
	public CountSearchByFieldsRecords(Domain domain,String dbType) throws ValidateException {
		super();
		this.domain = domain;
		this.dbType = dbType;
		this.denied = domain.isVerbDenied("SearchByFieldsByPage");
		this.verbName = "countSearch" + this.domain.getCapFirstPlural() + "ByFieldsRecords";
	}

	public CountSearchByFieldsRecords() {
		super();
		this.dbType = "MariaDB";
	}
	
	public CountSearchByFieldsRecords(String dbType) {
		super();
		this.dbType = dbType;
	}
}
